package top.huxy.boot.aspect;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import top.huxy.boot.annotation.RequestCD;
import top.huxy.boot.exception.RequestAbortedException;
import top.huxy.boot.util.IPAddressUtils;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @Classname LimitRequestAspect
 * @Description 将RequestCD放到方法上，可以限制请求冷却，防止恶意连续请求
 * @Date 2021/9/13 14:49
 * @Created by huxy
 */
@Component
@Aspect
public class RequestCDAspect {
    private static ConcurrentHashMap<R,Long> map=new ConcurrentHashMap<>();

    // 定义切点
    // 让所有有@LimitRequest注解的方法都执行切面方法
    @Pointcut("@annotation(requestCD)")
    public void executionService(RequestCD requestCD) {
    }

    @Around("executionService(requestCD)")
    public Object doAround(ProceedingJoinPoint joinPoint, RequestCD requestCD) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getName();
        String ip = IPAddressUtils.getRequestIp();

        R r=new R(ip,className+methodName);
        if(map.containsKey(r)){
            Long oldTime = map.get(r);
            long now = System.currentTimeMillis();
            if(now-oldTime< requestCD.time()){
                throw new RequestAbortedException(requestCD.msg());
            }else{
                map.put(r, System.currentTimeMillis());
            }
        }else{
            map.put(r,System.currentTimeMillis());
        }

        return joinPoint.proceed();
    }

    @Data
    @AllArgsConstructor
    private static class R{
        private String ip;
        private String methodName;
    }
}
